package com.fyz.aaronfjava.common.handler;

import com.fyz.aaronfjava.common.constant.ErrorConstant;
import com.fyz.aaronfjava.common.constant.HttpConstant;
import com.fyz.aaronfjava.util.Assert;
import com.fyz.aaronfjava.util.Jwt;
import com.fyz.aaronfjava.util.StringUtil;
import org.assertj.core.util.Arrays;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Optional;

/**
 * @Author：AaronF
 * @Date：2024/1/31 13:49
 * @description api权限验证拦截器
 */
@Component
public class ApiRoleHandler implements HandlerInterceptor {

    /**
     * 身份验证
     * @param req
     * @param resp
     * @param handler 要求类型为HandlerMethod，使用spring接口映射注解，都可以得到该对象
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler){
        if (handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod)handler;
            ApiRole apiRole = handlerMethod.getMethod().getAnnotation(ApiRole.class);
            // 判断是否需要权限认证
            Optional.ofNullable(apiRole).ifPresent(val -> {
                // 身份鉴权的信息存放在token
                Map<String, Object> claim = parseToken(req);
                Assert.notNull(claim, ErrorConstant.AUTH_EXPIRED_MSG);
                Assert.isTrue(authRole(val, claim),ErrorConstant.AUTH_FAILURE_MSG);
            });
        }
        return true;
    }

    /**
     * 对其身份进行认证
     * @param apiRole
     * @param claim
     * @return
     */
    private boolean authRole(ApiRole apiRole,Map<String, Object> claim){
        int value = apiRole.value();
        // 判断是否大于等于配置的level
        Integer level = (Integer) claim.get(Jwt.LEVEL);
        boolean levelFlag = value <= 0 || (level != null && level >= value);
        boolean allowFlag;
        if (apiRole.allow()){
            // 判断白名单
            allowFlag = Arrays.isNullOrEmpty(apiRole.white())
                    || StringUtil.contain((String) claim.get(Jwt.ROLE),apiRole.white());
        }else {
            // 判断黑名单
            allowFlag = Arrays.isNullOrEmpty(apiRole.black())
                    || !StringUtil.contain((String) claim.get(Jwt.ROLE),apiRole.black());
        }
        return levelFlag && allowFlag;
    }

    /**
     * 获取token
     * @param req
     * @return
     */
    private Map<String,Object> parseToken(HttpServletRequest req){
        String token = req.getHeader(HttpConstant.TOKEN_HEADER);
        // 校验token有效期
        if (!Jwt.validate(token)){
            return null;
        }
        return Jwt.parse(token);
    }

}
